package main

import "fmt"

/*

======================== 函数的基本语法 ========================

func 函数名（形参列表）（返回值列表）{
	执行语句...
	return 返回值列表 // 可以有，也可以没有
}

======================== init 函数 ========================

执行顺序：
如果一个文件中同时包含全局变量定义，init函数，main函数，
则执行的流程 全局变量定义 —> init函数 -> main函数


======================== 闭包， 匿名函数 ========================

闭包是一个函数与其相关的引用环境组合的一个整体（实体）

======================== defer ========================

defer ： 在函数中，经常需要创建资源（数据库连接，文件句柄，锁等）,为了在函数执行完成后，及时释放支援，Go的设计者提供defer（延时机制）
*/

// 全局的匿名函数
var (
	multi = func(n1 int, n2 int) int {
		return n1 * n2
	}
)

// 累加器 闭包
func AddUpper() func(int) int {
	var n int = 10
	return func(x int) int {
		n = n + x
		return n
	}
}

func main_i() {

	defer println(" defer 。。。。。。。。。。。 ")

	add := func(n1 int, n2 int) int {
		return n1 + n2
	}(10, 20)
	println("result = ", add)

	sub := func(n1 int, n2 int) int {
		return n1 - n2
	}

	result2 := sub(10, 30)
	println("result = ", result2)

	result3 := multi(2, 102)
	println("result = ", result3)

	println(" ====================== ")
	fA := AddUpper()
	println(fA(1))
	println(fA(2))
	println(fA(10))
}

func getSum(n1 int, n2 int) int {
	return n1 + n2
}

// 自定义数据类型，这里相当于一个别名
type mySum func(int, int) int

// 函数可以作为形参
func myFun(funV func(int, int) int, n1 int, n2 int) int {
	return funV(n1, n2)
}

func myFun2(funV mySum, n1 int, n2 int) int {
	return funV(n1, n2)
}

func main() {
	funVal := myFun(getSum, 10, 20)
	fmt.Println(funVal)
	funVal = myFun2(getSum, 20, 40)
	fmt.Println(funVal)

}
